<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Base64 图片解析预览工具</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            min-height: 100vh;
            padding: 20px;
        }

        .container {
            max-width: 1200px;
            margin: 0 auto;
            background: white;
            border-radius: 16px;
            box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
            overflow: hidden;
        }

        .header {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
            padding: 30px;
            text-align: center;
        }

        .header h1 {
            font-size: 28px;
            margin-bottom: 10px;
        }

        .header p {
            opacity: 0.9;
            font-size: 14px;
        }

        .content {
            padding: 30px;
        }

        .input-section {
            margin-bottom: 30px;
        }

        .input-label {
            display: block;
            font-weight: 600;
            margin-bottom: 10px;
            color: #333;
            font-size: 14px;
        }

        .input-area {
            position: relative;
        }

        textarea {
            width: 100%;
            min-height: 200px;
            padding: 15px;
            border: 2px solid #e0e0e0;
            border-radius: 8px;
            font-family: 'Courier New', monospace;
            font-size: 12px;
            resize: vertical;
            transition: border-color 0.3s;
        }

        textarea:focus {
            outline: none;
            border-color: #667eea;
        }

        .drop-zone {
            border: 2px dashed #667eea;
            border-radius: 8px;
            padding: 40px;
            text-align: center;
            background: #f8f9ff;
            cursor: pointer;
            transition: all 0.3s;
            margin-top: 15px;
        }

        .drop-zone:hover {
            background: #f0f2ff;
            border-color: #764ba2;
        }

        .drop-zone.dragover {
            background: #e8ebff;
            border-color: #764ba2;
            transform: scale(1.02);
        }

        .drop-zone-text {
            color: #667eea;
            font-size: 16px;
            margin-bottom: 10px;
        }

        .drop-zone-hint {
            color: #999;
            font-size: 12px;
        }

        .button-group {
            display: flex;
            gap: 10px;
            margin-top: 15px;
            flex-wrap: wrap;
        }

        .btn {
            padding: 12px 24px;
            border: none;
            border-radius: 8px;
            font-size: 14px;
            font-weight: 600;
            cursor: pointer;
            transition: all 0.3s;
            flex: 1;
            min-width: 120px;
        }

        .btn-primary {
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            color: white;
        }

        .btn-primary:hover {
            transform: translateY(-2px);
            box-shadow: 0 5px 15px rgba(102, 126, 234, 0.4);
        }

        .btn-secondary {
            background: #f5f5f5;
            color: #333;
        }

        .btn-secondary:hover {
            background: #e0e0e0;
        }

        .btn-danger {
            background: #ff4757;
            color: white;
        }

        .btn-danger:hover {
            background: #ff3838;
        }

        .preview-section {
            margin-top: 30px;
        }

        .preview-container {
            border: 2px solid #e0e0e0;
            border-radius: 8px;
            padding: 20px;
            background: #fafafa;
            min-height: 200px;
            display: flex;
            align-items: center;
            justify-content: center;
        }

        .preview-image {
            max-width: 100%;
            max-height: 600px;
            border-radius: 8px;
            box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
        }

        .preview-placeholder {
            color: #999;
            text-align: center;
            font-size: 14px;
        }

        .info-section {
            margin-top: 20px;
            padding: 15px;
            background: #f8f9ff;
            border-radius: 8px;
            border-left: 4px solid #667eea;
        }

        .info-item {
            margin: 8px 0;
            font-size: 13px;
            color: #666;
        }

        .info-label {
            font-weight: 600;
            color: #333;
            display: inline-block;
            min-width: 100px;
        }

        .error-message {
            margin-top: 15px;
            padding: 12px;
            background: #ffe5e5;
            border-left: 4px solid #ff4757;
            border-radius: 4px;
            color: #c92a2a;
            font-size: 13px;
            display: none;
        }

        .error-message.show {
            display: block;
        }

        .success-message {
            margin-top: 15px;
            padding: 12px;
            background: #e5ffe5;
            border-left: 4px solid #28a745;
            border-radius: 4px;
            color: #155724;
            font-size: 13px;
            display: none;
        }

        .success-message.show {
            display: block;
        }

        .tips {
            margin-top: 20px;
            padding: 15px;
            background: #fff9e6;
            border-radius: 8px;
            border-left: 4px solid #ffc107;
        }

        .tips-title {
            font-weight: 600;
            color: #856404;
            margin-bottom: 8px;
        }

        .tips-list {
            list-style: none;
            padding-left: 0;
        }

        .tips-list li {
            font-size: 13px;
            color: #856404;
            margin: 5px 0;
            padding-left: 20px;
            position: relative;
        }

        .tips-list li:before {
            content: "•";
            position: absolute;
            left: 0;
            color: #ffc107;
            font-weight: bold;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>🖼️ Base64 图片解析预览工具</h1>
            <p>支持解析和预览 Base64 编码的图片数据</p>
        </div>

        <div class="content">
            <div class="input-section">
                <label class="input-label">Base64 图片数据：</label>
                <div class="input-area">
                    <textarea id="base64Input" placeholder="请输入 Base64 图片数据，支持以下格式：&#10;1. ...&#10;2. iVBORw0KGgoAAAANS...&#10;&#10;或者直接粘贴图片文件到下方拖拽区域"></textarea>
                </div>

                <div class="drop-zone" id="dropZone">
                    <div class="drop-zone-text">📁 拖拽图片文件到这里</div>
                    <div class="drop-zone-hint">或点击选择文件</div>
                    <input type="file" id="fileInput" accept="image/*" style="display: none;">
                </div>

                <div class="button-group">
                    <button class="btn btn-primary" onclick="parseBase64()">解析预览</button>
                    <button class="btn btn-secondary" onclick="clearAll()">清空</button>
                    <button class="btn btn-secondary" onclick="copyBase64()">复制 Base64</button>
                    <button class="btn btn-danger" onclick="downloadImage()">下载图片</button>
                </div>

                <div class="error-message" id="errorMessage"></div>
                <div class="success-message" id="successMessage"></div>
            </div>

            <div class="preview-section">
                <label class="input-label">图片预览：</label>
                <div class="preview-container" id="previewContainer">
                    <div class="preview-placeholder">暂无图片预览</div>
                </div>

                <div class="info-section" id="infoSection" style="display: none;">
                    <div class="info-item">
                        <span class="info-label">图片格式：</span>
                        <span id="imageFormat">-</span>
                    </div>
                    <div class="info-item">
                        <span class="info-label">图片尺寸：</span>
                        <span id="imageSize">-</span>
                    </div>
                    <div class="info-item">
                        <span class="info-label">文件大小：</span>
                        <span id="fileSize">-</span>
                    </div>
                    <div class="info-item">
                        <span class="info-label">Base64 长度：</span>
                        <span id="base64Length">-</span>
                    </div>
                </div>
            </div>

            <div class="tips">
                <div class="tips-title">💡 使用提示：</div>
                <ul class="tips-list">
                    <li>支持直接粘贴 Base64 字符串（带或不带 data URI 前缀）</li>
                    <li>支持拖拽图片文件到拖拽区域自动转换</li>
                    <li>支持点击拖拽区域选择图片文件</li>
                    <li>支持 PNG、JPEG、GIF、WebP、BMP 等常见图片格式</li>
                    <li>可以复制解析后的 Base64 数据或下载预览的图片</li>
                </ul>
            </div>
        </div>
    </div>

    <script>
        let currentBase64 = '';
        let currentImageData = null;

        // 初始化
        document.addEventListener('DOMContentLoaded', function() {
            const dropZone = document.getElementById('dropZone');
            const fileInput = document.getElementById('fileInput');
            const base64Input = document.getElementById('base64Input');

            // 点击拖拽区域选择文件
            dropZone.addEventListener('click', () => {
                fileInput.click();
            });

            // 文件选择
            fileInput.addEventListener('change', (e) => {
                const file = e.target.files[0];
                if (file && file.type.startsWith('image/')) {
                    convertFileToBase64(file);
                } else {
                    showError('请选择有效的图片文件！');
                }
            });

            // 拖拽事件
            dropZone.addEventListener('dragover', (e) => {
                e.preventDefault();
                dropZone.classList.add('dragover');
            });

            dropZone.addEventListener('dragleave', () => {
                dropZone.classList.remove('dragover');
            });

            dropZone.addEventListener('drop', (e) => {
                e.preventDefault();
                dropZone.classList.remove('dragover');
                
                const file = e.dataTransfer.files[0];
                if (file && file.type.startsWith('image/')) {
                    convertFileToBase64(file);
                } else {
                    showError('请拖拽有效的图片文件！');
                }
            });

            // 监听粘贴事件
            document.addEventListener('paste', (e) => {
                const items = e.clipboardData.items;
                for (let i = 0; i < items.length; i++) {
                    if (items[i].type.indexOf('image') !== -1) {
                        const file = items[i].getAsFile();
                        convertFileToBase64(file);
                        e.preventDefault();
                        break;
                    }
                }
            });

            // 监听输入框变化（实时预览）
            base64Input.addEventListener('input', debounce(() => {
                const value = base64Input.value.trim();
                if (value.length > 100) { // 只有输入足够长时才自动预览
                    parseBase64();
                }
            }, 500));
        });

        // 防抖函数
        function debounce(func, wait) {
            let timeout;
            return function executedFunction(...args) {
                const later = () => {
                    clearTimeout(timeout);
                    func(...args);
                };
                clearTimeout(timeout);
                timeout = setTimeout(later, wait);
            };
        }

        // 将文件转换为 Base64
        function convertFileToBase64(file) {
            const reader = new FileReader();
            reader.onload = (e) => {
                const base64 = e.target.result;
                document.getElementById('base64Input').value = base64;
                currentBase64 = base64;
                parseBase64();
                showSuccess('图片文件已转换为 Base64 格式！');
            };
            reader.onerror = () => {
                showError('文件读取失败！');
            };
            reader.readAsDataURL(file);
        }

        // 解析 Base64 数据
        function parseBase64() {
            const input = document.getElementById('base64Input').value.trim();
            
            if (!input) {
                showError('请输入 Base64 图片数据！');
                return;
            }

            hideMessages();

            try {
                let base64Data = input;

                // 处理 data URI 格式
                if (base64Data.startsWith('data:image/')) {
                    currentBase64 = base64Data;
                } else {
                    // 如果不是 data URI 格式，尝试自动检测格式
                    // 先尝试 PNG
                    if (base64Data.startsWith('iVBORw0KGgo')) {
                        currentBase64 = 'data:image/png;base64,' + base64Data;
                    }
                    // 尝试 JPEG
                    else if (base64Data.startsWith('/9j/4AAQ')) {
                        currentBase64 = 'data:image/jpeg;base64,' + base64Data;
                    }
                    // 尝试 GIF
                    else if (base64Data.startsWith('R0lGODlh')) {
                        currentBase64 = 'data:image/gif;base64,' + base64Data;
                    }
                    // 尝试 WebP
                    else if (base64Data.startsWith('UklGR')) {
                        currentBase64 = 'data:image/webp;base64,' + base64Data;
                    }
                    // 默认使用 PNG
                    else {
                        currentBase64 = 'data:image/png;base64,' + base64Data;
                    }
                }

                // 创建图片对象
                const img = new Image();
                img.onload = () => {
                    displayImage(img, currentBase64);
                    updateImageInfo(img, currentBase64);
                    showSuccess('图片解析成功！');
                };
                img.onerror = () => {
                    showError('Base64 数据无效或图片格式不支持！请检查数据是否正确。');
                };
                img.src = currentBase64;
                currentImageData = img;

            } catch (error) {
                showError('解析失败：' + error.message);
                console.error('解析错误：', error);
            }
        }

        // 显示图片
        function displayImage(img, base64) {
            const container = document.getElementById('previewContainer');
            container.innerHTML = '';
            
            const imageElement = document.createElement('img');
            imageElement.src = base64;
            imageElement.className = 'preview-image';
            imageElement.alt = '预览图片';
            container.appendChild(imageElement);
        }

        // 更新图片信息
        function updateImageInfo(img, base64) {
            const infoSection = document.getElementById('infoSection');
            infoSection.style.display = 'block';

            // 提取格式
            const formatMatch = base64.match(/data:image\/([^;]+)/);
            const format = formatMatch ? formatMatch[1].toUpperCase() : '未知';
            document.getElementById('imageFormat').textContent = format;

            // 图片尺寸
            document.getElementById('imageSize').textContent = `${img.width} × ${img.height} 像素`;

            // 文件大小（Base64 解码后的大小）
            const base64Data = base64.split(',')[1] || base64;
            const binaryLength = atob(base64Data).length;
            const fileSizeKB = (binaryLength / 1024).toFixed(2);
            const fileSizeMB = (binaryLength / (1024 * 1024)).toFixed(2);
            document.getElementById('fileSize').textContent = 
                binaryLength > 1024 * 1024 
                    ? `${fileSizeMB} MB` 
                    : `${fileSizeKB} KB`;

            // Base64 长度
            document.getElementById('base64Length').textContent = `${base64Data.length.toLocaleString()} 字符`;
        }

        // 清空所有
        function clearAll() {
            document.getElementById('base64Input').value = '';
            document.getElementById('previewContainer').innerHTML = '<div class="preview-placeholder">暂无图片预览</div>';
            document.getElementById('infoSection').style.display = 'none';
            currentBase64 = '';
            currentImageData = null;
            hideMessages();
        }

        // 复制 Base64
        function copyBase64() {
            if (!currentBase64) {
                showError('没有可复制的 Base64 数据！请先解析图片。');
                return;
            }

            const input = document.createElement('textarea');
            input.value = currentBase64;
            document.body.appendChild(input);
            input.select();
            document.execCommand('copy');
            document.body.removeChild(input);
            showSuccess('Base64 数据已复制到剪贴板！');
        }

        // 下载图片
        function downloadImage() {
            if (!currentImageData || !currentBase64) {
                showError('没有可下载的图片！请先解析图片。');
                return;
            }

            try {
                const formatMatch = currentBase64.match(/data:image\/([^;]+)/);
                const format = formatMatch ? formatMatch[1] : 'png';
                const filename = `image_${Date.now()}.${format}`;

                // 创建下载链接
                const link = document.createElement('a');
                link.href = currentBase64;
                link.download = filename;
                document.body.appendChild(link);
                link.click();
                document.body.removeChild(link);
                showSuccess('图片下载成功！');
            } catch (error) {
                showError('下载失败：' + error.message);
            }
        }

        // 显示错误消息
        function showError(message) {
            const errorDiv = document.getElementById('errorMessage');
            errorDiv.textContent = message;
            errorDiv.classList.add('show');
            document.getElementById('successMessage').classList.remove('show');
        }

        // 显示成功消息
        function showSuccess(message) {
            const successDiv = document.getElementById('successMessage');
            successDiv.textContent = message;
            successDiv.classList.add('show');
            document.getElementById('errorMessage').classList.remove('show');
        }

        // 隐藏所有消息
        function hideMessages() {
            document.getElementById('errorMessage').classList.remove('show');
            document.getElementById('successMessage').classList.remove('show');
        }
    </script>
</body>
</html>

